package com.aspire.wap.core.http;

import java.security.Security;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jodd.cache.Cache;
import jodd.cache.LRUCache;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.aspire.core.gw.GatewayCenter;
import com.aspire.core.match.ua.object.Device;
import com.aspire.core.match.ua.UACenter;
import com.aspire.wap.core.common.StringUtil;
import com.aspire.wap.core.common.ThreeDesUtil;
import com.aspirecn.core.ShareCommon;
import com.aspirecn.core.commons.HttpUtils;
import com.aspirecn.core.object.Haoduan;

/**
 * 封装对HttpRequest的一些处理
 * 
 * @version 1.0
 * @since 2007-08-01 1、获取request中的参数，按不同类型给出包含默认值的获取方式
 *        2、获取用户手机号，不能获取抛出异常。获取手机号去掉86或者+86前缀，只保留11位本体 3、获取终端UA信息 4、判断手机号是否移动手机号
 * 
 * @author luozhi
 * 
 */
public class RequestUtil {

	private static UACenter uaCenter = new UACenter();
	
	/**
	 * 获取整型参数
	 * 
	 * @param req
	 * @param para
	 * @param defValue
	 * @return
	 */
	public static int getIntParameter(HttpServletRequest req, String para,
			int defValue) {
		return HttpUtils.getIntParameter(req, para, defValue);
	}

	/**
	 * 获取浮点型参数
	 * 
	 * @param req
	 * @param para
	 * @param defValue
	 * @return
	 */
	public static float getFloatParameter(HttpServletRequest req, String para,
			float defValue) {
		return HttpUtils.getFloatParameter(req, para, defValue);
	}

	/**
	 * 获取boolean型变量
	 * 
	 * @param req
	 * @param para
	 * @param defValue
	 * @return
	 */
	public static boolean getBooleanParameter(HttpServletRequest req,
			String para, boolean defValue) {
		return HttpUtils.getBooleanParameter(req, para, defValue);
	}

	/**
	 * 获取字符型参数
	 * 
	 * @param req
	 * @param para
	 * @param defValue
	 * @return
	 */
	public static String getStringParameter(HttpServletRequest req,
			String para, String defValue) {
		return HttpUtils.getStringParameter(req, para, defValue);
	}

	/**
	 * 获取用户手机号，返回是11位手机号实体。不能获取抛出异常
	 * 
	 * @param req
	 * @return
	 * @throws Exception
	 */
	public static String getMobile(HttpServletRequest req) throws Exception {

		// 2012-05-16 兼容获取四川手机号的方法
		String scMobile = CmnetCookieUtil.getMobileFromCookie(req);
		// 09-27 舒伟
		//String scMobile = CmnetCookieUtil.getSCMobile(req);		
		if (StringUtils.isNotEmpty(scMobile)) {
			return formatMobile(scMobile);
		}
		// 四川结束

		// 从cookie尝试，河南用
		String hnMobile = getMobileFromCookie( req );
		if (StringUtils.isNotEmpty(hnMobile)) {
			return formatMobile(hnMobile);
		}
		
		
		GatewayCenter gatewayCenter = new GatewayCenter();
		if (gatewayCenter.getGateWay(req) != GatewayCenter.CMWAP_GATEWAY) {
			throw new Exception("非wap网关，不能获取用户手机号");
		}

		String tmp = HttpUtils.getHeaderIgnoreCase(req, "x-up-calling-line-id");
		if (StringUtils.isBlank(tmp)) {
			tmp = HttpUtils.getHeaderIgnoreCase(req, "x-nokia-msisdn");
		}
		if (StringUtils.isBlank(tmp)) {
			tmp = HttpUtils.getHeaderIgnoreCase(req, "MISC_MSISDN");
		}

		if (StringUtils.isBlank(tmp)) {
			throw new Exception("未正常获取到用户手机号");
		} else {
			
			return formatMobile(tmp);
		}
	}

	/**
	 * 获取用户手机号，返回是11位手机号实体。不能获取抛出异常
	 * 
	 * @param req
	 * @return
	 * @throws Exception
	 */
	public static String getMobileNoneException(HttpServletRequest req) {
		String returnStr = "";
		
		try {
			returnStr = getMobile(req);
		} catch (Exception ex) {

		}
		
		return StringUtils.trimToEmpty(returnStr);
	}

	public static String getBrowse(HttpServletRequest req) {
		String srcua = getOriginalUserAgent(req);

		//Map<String, String> map = new HashMap<String, String>();
		String browses = "MQQBrowser/Mini2,MQQBrowser/Mini3,MQQBrowser/1,MQQBrowser/2,MQQBrowser/3,MQQBrowser,";
		browses += "UCWEB/6,UCWEB7,UCWEB8,UCWEB";
		browses += "Opera8,Opera 8,Opera9,OPERA/8,OPERA/9,Opera/9,Opera 9,9.5 Opera,Opera";
		browses += "OpenWave5,OpenWave6,Openwave/6,OpenWave7,OpenWave 7,OpenWave";
		browses += "Dolfin/1,Dolfin1,Dolfin/2,Dolfin2,Dolfin";
		browses += "NetFront/3,NetFront 3,NetFront3,NetFront";
		browses += "MTK";

		String[] keywords = StringUtils.split(browses,",");
		
		for( int i = 0; i < keywords.length; i++ )
		{
			if (StringUtils.containsIgnoreCase(srcua, keywords[i])) {
				return keywords[i];
			}
		}
		
		return "";
	}

	public static String getUA(HttpServletRequest req) {

		String ua = getOriginalUserAgent(req);
		if (StringUtils.isEmpty(ua)) {
			return ua;
		}
		// 先从request里读取缓存
		String requestUA = (String) req.getAttribute("mobile_ua_" + ua);
		if (StringUtils.isNotEmpty(requestUA)) {

			return requestUA;
		} else {
			// 保存原始ua信息
			requestUA = ua;
		}

		// wxn modify
		// ua = formPamsUserAgent(ua);
		// 写入request缓存

		// wxn add 2013-09-29 加入大缓存
		ua = localUACacheService.get(requestUA);
		if( ua == null )
		{
			ua = formatUAByCenter(req, requestUA);
			localUACacheService.put(requestUA, StringUtils.trimToEmpty(ua));
		}

		// 6-15 刘咏亭邮件要求
		if (StringUtils.isNotBlank(ua) && StringUtils.length(ua) > 60 && StringUtils.contains(ua, "/")) {
			ua = StringUtils.substringBefore(ua, "/");
		}

		ua = StringUtils.trimToEmpty(ua);
		
		req.setAttribute("mobile_ua_" + requestUA, ua);
		
		return ua;
	}
	//ua适配，提供给上面的方法提高速度的
	public static Cache<String,String> localUACacheService = new LRUCache<String,String>(20000);
	
	
	//sharecommon.jsp需要
	public static String getUA(HttpServletRequest req, String ua) {

		if (StringUtils.isEmpty(ua)) {
			return ua;
		}

		// wxn add
		ua = formatUAByCenter(req, ua);

		// 6-15 刘咏亭邮件要求
		if (StringUtils.isNotBlank(ua) && StringUtils.length(ua) > 60 && StringUtils.contains(ua, "/")) {
			ua = StringUtils.substringBefore(ua, "/");
		}

		return ua;
	}

	public static String getOriginalUserAgent(HttpServletRequest request) {
		String ua = HttpUtils.getHeaderIgnoreCase(request, "User-Agent");		
		return StringUtils.trimToEmpty(ua);
	}

	private static CopyOnWriteArrayList<String> SPUA = null;

	private static void loadSPUA() {
		SPUA = new CopyOnWriteArrayList<String>();
		SPUA.add("iPhone");
		SPUA.add("SHARP/1.0/SH8010C");
		SPUA.add("Sharp/1.0/SH9010C");
		SPUA.add("LG/BL42");
		SPUA.add("LG/GD580");
		SPUA.add("LG/GT505e");
		SPUA.add("LG/KC910");
		SPUA.add("LG/KC910e");
		SPUA.add("LG/KE990");
		SPUA.add("LG/KF750");
		SPUA.add("LG/KF755");
		SPUA.add("LG/KU800");
		SPUA.add("LG/U400");
	}

	public static String formPamsUserAgent(String ua) {
		if (StringUtils.isNotBlank(ua)) {
			if (SPUA == null) {
				loadSPUA();
			}
			// 判断指定UA
			// 2012-2-13 wxn modify
			Iterator<String> ite = SPUA.iterator();
			while (ite.hasNext()) {
				String tempSpua = ite.next();
				if (StringUtils.contains(ua, tempSpua)) {
					return tempSpua;
				}
			}
			// for (String spua : SPUA) {
			// if (ua.indexOf(spua) != -1) {
			// return spua;
			// }
			// }
			// 正则匹配
			String sRegx = "(Samsung-SGH|ZTE |SKYWORTH |MOT-Nokia |MOT-NOKIA |MOT-iPod |AMOI |TCL |Philips |PHILIPS |PANTECH |MOT-PEBL |MOTORAZR |DCTC |DCTC|Compal- |CECT |Capitel |BW-NEO200 |BW-ANASTA |BIRD |Bird |BENQ |BenQ |BENQ|MOT-A780\\(Mozilla/4.0\\)|dopod ?|MOT-ROKR |LG |LG-G832 |LG-KG118cv100 |LG-KG328 |LG-KG90 |Dopod|dopod|SGH|SCH|SAMSUNG|Nokia|MOT|Motorola|LENOVO|SonyEricsson|NEC|Panasonic|BIRD|Sharp|Haier|HAIER|SEC|KEJIAN|VK|Amoi|PHILIPS|GIONEE|BenQ|ZTE|OT|SKYWORTH|SZV|SIE|TCL|BlackBerry|AHONG|SAGEM|SHARP|Mitsu|LG|SOUTEC|CLOVE|Yulong|YuLong|PANTECH|Huawei|HS|EASTCOM|IAC|Bird|Philips|kejian|Dnet|Compal|ASUS|KONKA|AMOI|CECT|HTC)[^/^\\*\\s]*";
			Pattern p = Pattern.compile(sRegx);
			Matcher m = p.matcher(ua);
			if (m.find()) {
				// m.lookingAt();
				ua = m.group(0);
			} else {
				int idx = ua.indexOf('/');
				if (-1 != idx) {
					ua = ua.substring(0, idx);
				}
			}
			// 正则匹配 end
		}
		return ua;
	}

	/**
	 * 根据http header ACCEPT判断是否支持wap2
	 * 
	 * @param request
	 * @return
	 * @author huyunan 2010-7-2 下午05:45:37
	 */
	public static boolean isWap2Support(HttpServletRequest request) {
		boolean isSupport = false;
		String accept = HttpUtils.getHeaderIgnoreCase(request, "ACCEPT");		
				//request.getHeader("ACCEPT");
		if (StringUtils.isNotBlank(accept)) {
			if (accept.indexOf("html") != -1 || accept.indexOf("MSIE 6") != -1
					|| accept.indexOf("Mozilla") != -1
					|| accept.indexOf("MSIE") != -1
					|| accept.indexOf("Browser/WAP 2.0") != -1
					|| accept.indexOf("Safari") != -1) {
				isSupport = true;
			}
		}

		String ua = getOriginalUserAgent( request );
		
		if (StringUtils.isNotBlank(ua)) {
			if (StringUtils.containsIgnoreCase(ua, "MSIE 6")
					|| StringUtils.containsIgnoreCase(ua, "Mozilla")
					|| StringUtils.containsIgnoreCase(ua, "MSIE")
					|| StringUtils.containsIgnoreCase(ua, "Browser/WAP 2.0")
					|| StringUtils.containsIgnoreCase(ua, "Safari")
					|| StringUtils.containsIgnoreCase(ua, "ios")
					|| StringUtils.containsIgnoreCase(ua, "android")
					|| StringUtils.containsIgnoreCase(ua, "iphone")) {
				isSupport = true;
			}
		}

		return isSupport;
	}

	/**
	 * 检查手机号码是否移动手机号
	 * 
	 * @param mid
	 * @return
	 */
	public static boolean isCMCC(String mid) {
		
		String mobile = formatMobile( mid );
		
		if( StringUtils.isNotBlank(mobile) )
		{
			String mobilePrefix = StringUtils.substring(mobile, 0, 7);
			Haoduan haoduan = ShareCommon.getInstance().getHaoduanCache().getHaoduan(NumberUtils.toInt(mobilePrefix));
			
			if( haoduan != null )
			{
				return true;
			}
		}
		
		return false;
		
//		Pattern p = Pattern
//				.compile("(13[4,5,6,7,8,9]|14[7]|15[1,2,3,0,7,8,9]|18[8,7,2,3,2])\\d{8}");
//		
//		Matcher m = p.matcher(mid);
//
//		return m.matches();
		
//		ShareCommon.getInstance().getHaoduanCache().getHaoduan(mobilePrefix)
		
		
	}


	/**
	 * 格式化手机号，去掉不需要的字符
	 * @param mobile
	 * @return
	 */
	public static String formatMobile( String mobile )
	{
		String mob = StringUtils.trimToEmpty(mobile);
		int length = StringUtils.length( mob );
		
		if ((length == 13 && StringUtils.startsWith(mob, "86"))
				|| (length == 14 && StringUtils.startsWith(mob, "+86"))) {
			mob = StringUtils.substringAfter(mob, "86");
		}
		
		if( NumberUtils.isNumber(mob) && StringUtils.length(mob) == 11 )
		{
			return mob;
		}
		
		return null;
	}
	
	

	private static String formatUAByCenter(HttpServletRequest request, String ua) {
		//initCenterObject(request);
		Device device = uaCenter.matchUA(ua);
		//Device device = ShareCommon.getInstance().getUACache().matchUA(ua);
		if (device != null && StringUtils.isNotEmpty(device.getDevice_ua())) {
			// System.out.println( device );
			return device.getDevice_ua();
		}

		if (device != null && StringUtils.isNotEmpty(device.getDevice_os_ua())) {
			// System.out.println( device );
			return device.getDevice_os_ua();
		}

		if (device != null && StringUtils.isNotEmpty(device.getDevice_name())) {
			// System.out.println( device );
			return device.getDevice_name();
		}

		if (StringUtils.containsIgnoreCase(ua, "iPhone")
				&& StringUtils.containsIgnoreCase(ua, "OS 5")) {
			return "iPhone 4S";
		}

		if (StringUtils.containsIgnoreCase(ua, "iPhone")
				&& StringUtils.containsIgnoreCase(ua, "OS 4")) {
			return "iPhone 4";
		}

		if (StringUtils.containsIgnoreCase(ua, "iPhone")) {
			return "iPhone";
		}

		if (StringUtils.containsIgnoreCase(ua, "android")
				&& StringUtils.containsIgnoreCase(ua, "1.")) {
			return "android 1.6";
		}

		if (StringUtils.containsIgnoreCase(ua, "android")
				&& StringUtils.containsIgnoreCase(ua, "2.")) {
			return "android 2.0";
		}

		if (StringUtils.containsIgnoreCase(ua, "android")
				&& StringUtils.containsIgnoreCase(ua, "3.")) {
			return "android 3.0";
		}

		if (StringUtils.containsIgnoreCase(ua, "android")
				&& StringUtils.containsIgnoreCase(ua, "4.")) {
			return "android 4.0";
		}

		if (StringUtils.containsIgnoreCase(ua, "UCWEB8")) {
			return "UCWEB8";
		}

		if (StringUtils.containsIgnoreCase(ua, "UCWEB7")) {
			return "UCWEB7";
		}

		if (StringUtils.containsIgnoreCase(ua, "UCWEB")) {
			return "UCWEB";
		}

		if (StringUtils.containsIgnoreCase(ua, "MQQBrowser")) {
			return "MQQBrowser";
		}

		if (StringUtils.containsIgnoreCase(ua, "Opera")) {
			return "Opera";
		}

		if (StringUtils.containsIgnoreCase(ua, "UCWEB")) {
			return "UCWEB";
		}

		if (StringUtils.containsIgnoreCase(ua, "Mozilla")) {
			return "Mozilla";
		}

		if (StringUtils.containsIgnoreCase(ua, "AppleWebKit")) {
			return "AppleWebKit";
		}

		if (StringUtils.containsIgnoreCase(ua, "MSIE")) {
			return "MSIE";
		}

		return ua;
	}
	
	public static void setMobileToCookie( HttpServletResponse response,Long mobile ) throws Exception
	{
		byte[] src = mobile.toString().getBytes();
		
		Security.addProvider(new com.sun.crypto.provider.SunJCE());
		byte[] encoded = ThreeDesUtil.encryptMode(ThreeDesUtil.DES_KEY.getBytes(), src);
		String hexString = StringUtil.bytesToHexString(encoded);
		
		Cookie cookie = new Cookie("smtc", hexString);
		cookie.setPath("/");
		cookie.setMaxAge(60*60*24*31);
		
		response.addCookie(cookie);
		
	}
	
	private static String getMobileFromCookie(HttpServletRequest request)
			throws Exception {
		String value = getCookie(request, "smtc");

		if (StringUtils.isNotEmpty(value)) {
			return new String(ThreeDesUtil.decryptMode(
					ThreeDesUtil.DES_KEY.getBytes(),
					StringUtil.hexStringToBytes(value)));
		}

		return null;
	}
	
	public static String getCookie( HttpServletRequest request, String name )
	{
		return HttpUtils.getCookieIgnoreCase(request, name);	
	}
	
	
	public static void main( String[] args )
	{
		System.out.println( isCMCC("+8619911364536") );
	}
}